from unipath import Path
from typing import Set, Dict
from loguru import logger
import sys
import shutil

# 配置日志
logger.remove()
logger.add(
    sys.stdout,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <level>{message}</level>",
    level="INFO",
    encoding='utf-8'
)
logger.add(
    Path("logs").mkdir(True) / "file_operations_{time:YYYY-MM-DD}.log",
    rotation="00:00",
    retention="30 days",
    encoding="utf-8"
)

# 常量定义
VIDEO_EXTENSIONS: Set[str] = {'.mp4', '.mkv', '.avi', '.mov', '.wmv', '.flv'}
VIRTUAL_EXTENSION: str = '.laoji'
SOURCE_VIDEO_PATH: Path = Path("scrapy_result/source_move_file.mkv")


def create_virtual_files(root_path: str) -> Dict:
    """
    为视频文件创建虚拟文件(.laoji)

    Args:
        root_path: 要处理的根目录路径

    Returns:
        处理结果统计
    """
    result = {
        "processed": 0,
        "skipped": 0,
        "failed": 0,
        "details": []
    }

    try:
        root = Path(root_path)
        if not root.exists():
            raise FileNotFoundError(f"目录不存在: {root_path}")

        logger.info(f"开始处理目录: {root_path}")

        # 使用unipath的walk方法遍历文件
        for file_path in root.walk(filter=Path.FILES):
            if file_path.ext.lower() in VIDEO_EXTENSIONS:
                virtual_file = Path(file_path.parent, file_path.name + VIRTUAL_EXTENSION)

                try:
                    if virtual_file.exists():
                        logger.debug(f"虚拟文件已存在，跳过: {virtual_file}")
                        result["skipped"] += 1
                        continue

                    # 创建空文件
                    with open(virtual_file, 'wb', buffering=0) as _:
                        pass
                    logger.info(f"创建虚拟文件: {virtual_file}")
                    result["processed"] += 1
                    result["details"].append({
                        "action": "created",
                        "path": str(virtual_file)
                    })

                except Exception as e:
                    logger.error(f"创建虚拟文件失败: {virtual_file} - {e}")
                    result["failed"] += 1
                    result["details"].append({
                        "action": "failed",
                        "path": str(virtual_file),
                        "error": str(e)
                    })

        logger.success(f"处理完成: 成功={result['processed']}, 跳过={result['skipped']}, 失败={result['failed']}")
        return result

    except Exception as e:
        logger.exception(f"处理过程发生错误: {e}")
        raise


def restore_from_virtual_files(root_path: str) -> Dict:
    """
    从虚拟文件(.laoji)还原视频文件

    Args:
        root_path: 要处理的根目录路径

    Returns:
        处理结果统计
    """
    result = {
        "processed": 0,
        "skipped": 0,
        "failed": 0,
        "details": []
    }

    try:
        root = Path(root_path)
        source_video = SOURCE_VIDEO_PATH

        if not root.exists():
            raise FileNotFoundError(f"目录不存在: {root_path}")
        if not source_video.exists():
            raise FileNotFoundError(f"源视频文件不存在: {source_video}")

        logger.info(f"开始还原目录: {root_path}")

        # 遍历所有.laoji文件
        for virtual_file in root.walk(filter=Path.FILES):
            # 如果不是.laoji后缀的文件就跳过
            if virtual_file.ext.lower() != VIRTUAL_EXTENSION:
                continue

            # 获取目标文件路径（去掉.laoji后缀）
            target_file = Path(virtual_file.parent, virtual_file.stem)

            try:
                if target_file.exists():
                    logger.warning(f"目标文件已存在，跳过: {target_file}")
                    result["skipped"] += 1
                    continue

                # 复制源视频文件
                shutil.copy2(source_video, target_file)
                logger.info(f"还原视频文件: {target_file}")
                result["processed"] += 1
                result["details"].append({
                    "action": "restored",
                    "path": str(target_file)
                })

            except Exception as e:
                logger.error(f"还原视频文件失败: {target_file} - {e}")
                # 清理失败的文件
                if target_file.exists():
                    target_file.remove()
                result["failed"] += 1
                result["details"].append({
                    "action": "failed",
                    "path": str(target_file),
                    "error": str(e)
                })

        logger.success(f"还原完成: 成功={result['processed']}, 跳过={result['skipped']}, 失败={result['failed']}")
        return result

    except Exception as e:
        logger.exception(f"还原过程发生错误: {e}")
        raise


def print_results(create_result: Dict = None, restore_result: Dict = None) -> None:
    """打印处理结果"""
    if create_result:
        print("\n=== 创建虚拟文件结果 ===")
        print(f"成功: {create_result['processed']}")
        print(f"跳过: {create_result['skipped']}")
        print(f"失败: {create_result['failed']}")

        if create_result['failed'] > 0:
            print("\n失败详情:")
            for detail in create_result['details']:
                if detail['action'] == 'failed':
                    print(f"- {detail['path']}: {detail['error']}")

    if restore_result:
        print("\n=== 还原视频文件结果 ===")
        print(f"成功: {restore_result['processed']}")
        print(f"跳过: {restore_result['skipped']}")
        print(f"失败: {restore_result['failed']}")

        if restore_result['failed'] > 0:
            print("\n失败详情:")
            for detail in restore_result['details']:
                if detail['action'] == 'failed':
                    print(f"- {detail['path']}: {detail['error']}")


def main():
    """主函数"""
    try:
        root_path = r"D:\Videos"  # 要处理的目录路径

        # 创建虚拟文件
        create_result = create_virtual_files(root_path)

        # 从虚拟文件还原
        restore_result = restore_from_virtual_files(root_path)

        # 打印结果
        print_results(create_result, restore_result)

    except Exception as e:
        logger.error(f"程序执行失败: {e}")
        raise


if __name__ == "__main__":
    main()